package com.ning.run.service.impl;


import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.ning.run.POJO.PO.Graderecord;
import com.ning.run.POJO.PO.Memberinfo;
import com.ning.run.POJO.PO.Pointaction;
import com.ning.run.POJO.PO.Pointrecord;
import com.ning.run.POJO.TO.MemberInfoFindPassTO;
import com.ning.run.POJO.TO.MemberInfoLoginTO;
import com.ning.run.POJO.TO.MemberInfoRegisterTO;
import com.ning.run.POJO.VO.LoginVO;
import com.ning.run.common.constant.PointActionConstant;
import com.ning.run.common.exception.MyException;
import com.ning.run.common.utils.IpUtil;
import com.ning.run.common.utils.MailUtil;
import com.ning.run.common.utils.MyUtil;
import com.ning.run.common.utils.RandomUtil;
import com.ning.run.mapper.GraderecordMapper;
import com.ning.run.mapper.MemberinfoMapper;
import com.ning.run.mapper.PointactionMapper;
import com.ning.run.mapper.PointrecordMapper;
import com.ning.run.service.MemberinfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
* @author Ning
* @description 针对表【MEMBERINFO】的数据库操作Service实现
* @createDate 2022-12-09 20:45:57
*/
@Service
public class MemberinfoServiceImpl implements MemberinfoService{

    @Autowired
    MemberinfoMapper memberinfoMapper;

    @Autowired
    PointactionMapper pointactionMapper;

    @Autowired
    PointrecordMapper pointrecordMapper;

    @Autowired
    GraderecordMapper graderecordMapper;
    /**
     * @Description: 用户信息注册
     * @param: 前端传来的参数
     * @return void
     * @author: ning
     * @email: cxy_ning@163.com
     * @date: 2022/12/11 17:14
    */
    @Override
    public void register(MemberInfoRegisterTO registerTO) {
        //验证传入参数是否符合规范

        //判断用户名是否为空
        String nickname = registerTO.getNickname();
        if (MyUtil.StringIsBlank(nickname)){
            throw new MyException("昵称不能为空,请输入您的昵称!!!");
        }
        //判断密码是否为空 确认密码是否为空 两次密码是否相同
        String password1 = registerTO.getPassword1();
        if (MyUtil.StringIsBlank(password1))
            throw new MyException("密码不能为空,请输入您的密码!!!");

        String password2 = registerTO.getPassword2();
        if (MyUtil.StringIsBlank(password2))
            throw new MyException("请您确认密码");

        if (!password1.equals(password2))
            throw new MyException("两次密码不一致!!!");

        //看用户名是否重复
        Memberinfo dbMemberinfo = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname, nickname).one();
        if (dbMemberinfo!=null)
            throw new MyException("该用户已存在!!!");

        //将信息放入 Memberinfo 然后完成注册
        Memberinfo memberinfo = new Memberinfo();

        //将其他信息 放入 Memberinfo

        //用户昵称
        memberinfo.setNickname(registerTO.getNickname());

        //用户密码
        //将密码 加密后放入 Memberinfo   // TODO: 加密
        memberinfo.setPassword(registerTO.getPassword1());

        //用户性别
        memberinfo.setGender(registerTO.getGender());

        //用户年龄
        memberinfo.setAge(registerTO.getAge());

        //用户邮箱
        memberinfo.setEmail(registerTO.getEmail());

        //用户填写的省份
        memberinfo.setProvincecity(registerTO.getProvincecity());

        //用户地址
        memberinfo.setAddress(registerTO.getAddress());

        //用户手机号码
        memberinfo.setPhone(registerTO.getPhone());

        //用户密保问题
        memberinfo.setPasswordquestion(registerTO.getPasswordquestion());

        //用户设置的密保答案
        memberinfo.setPasswordanswer(registerTO.getPasswordanswer());

        //用户推荐人
        //判断是否有推荐人 有就给推荐人的推荐行为加分
        if(!MyUtil.StringIsBlank(registerTO.getRecommender())){
            //判断推荐人是否存在
            Memberinfo recommender = new LambdaQueryChainWrapper<>(memberinfoMapper)
                    .eq(Memberinfo::getNickname, registerTO.getRecommender())
                    .one();

            if (recommender == null){
                throw new MyException("该推荐人不存在!!!");
            }
            //给推荐人加分
            addPointAndRecordByAction(recommender.getNickname(), PointActionConstant.RECOMMEND);
        }

        //初始分数  注册行为加分
        memberinfo.setPoint(0);

        //注册时间
        memberinfo.setRegisterdate(new Date());

        //上一次登陆时间
        memberinfo.setLatestdate(null);

        //账号状态
        memberinfo.setStatus(0);

        //是否在线
        memberinfo.setIsonline(0);

        //账号等级的id
        memberinfo.setGradeid(1);

        //将 Memberinfo 插入数据库
        memberinfoMapper.insert(memberinfo);

        //注册行为加分
        addPointAndRecordByAction(memberinfo.getNickname(),PointActionConstant.REGISTER);
    }

    @Override
    public Memberinfo login(MemberInfoLoginTO loginTO) {
        //检查用户昵称，密码是否为空
        if (MyUtil.StringIsBlank(loginTO.getNickname())) {
            throw new MyException("用户名不能为空");
        }
        if (MyUtil.StringIsBlank(loginTO.getPassword())) {
            throw new MyException("密码不能为空!!!");
        }

        //查看该用户是否存在
        Memberinfo memberinfo = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname,loginTO.getNickname())
                .one();

        if (memberinfo==null) {
            throw new MyException("该用户不存在!!!");
        }

        //判断账号是否被禁用
        if (memberinfo.getStatus()==1) {
            throw new MyException("账号已被禁用!!!");
        }

        //判断用户账号密码是否正确
        if (!loginTO.getPassword().equals(memberinfo.getPassword())){
            throw new MyException("用户名或密码错误!!!");
        }

        //第一天登陆或者不是同一天则登陆行为加分
        if (memberinfo.getLatestdate()==null||!MyUtil.isSameDay(new Date(),memberinfo.getLatestdate())) {
            addPointAndRecordByAction(memberinfo.getNickname(), PointActionConstant.LOGIN);
        }

        //更新用户的上次登陆时间和用户的登陆状态
        new LambdaUpdateChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname,memberinfo.getNickname())
                .set(Memberinfo::getLatestdate,new Date())
                .set(Memberinfo::getIsonline,1).update();

        //返回用户信息
        return memberinfo;
    }

    @Override
    public void logout(int userId) {
        //清空session中的账号和密码 后面优化

        //修改用户的在线状态
        new LambdaUpdateChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getId,userId)
                .set(Memberinfo::getIsonline,0)
                .update();
    }

    /**
     * @Description: 用户行为加分
     * @param: userName 用户名字
     * @param: action 加分行为
     * @return void
     * @author: ning
     * @email: cxy_ning@163.com
     * @date: 2022/12/12 19:28
     */
    @Override
    public void addPointAndRecordByAction(String userName, String action) {

        //获得用户的积分情况、积分等级
        Memberinfo memberinfo = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname, userName)
                .one();

        //得到行为对应的分数,id
        Pointaction pointaction = new LambdaQueryChainWrapper<>(pointactionMapper)
                .eq(Pointaction::getActionname, action)
                .one();

        //新分数
        int newPoint = memberinfo.getPoint()+pointaction.getPoint();

        //得到新分数对应的等级
        Graderecord graderecord = new LambdaQueryChainWrapper<>(graderecordMapper)
                .le(Graderecord::getMinpoint, newPoint)
                .ge(Graderecord::getMaxpoint, newPoint)
                .one();

        //更新用户的积分(或等级)
        new LambdaUpdateChainWrapper<>(memberinfoMapper)
                //更新条件
                .eq(Memberinfo::getNickname,userName)
                //要更新的数据
                .set(Memberinfo::getPoint,newPoint)
                .set(Memberinfo::getGradeid,graderecord.getId())
                .update();


        //添加获得积分的记录
        Pointrecord pointrecord = new Pointrecord();
        //哪个用户的行为
        pointrecord.setNickname(userName);
        //获得积分的日期
        pointrecord.setReceivedate(new Date());
        //行为id
        pointrecord.setPointactionid(pointaction.getId());
        //添加记录
        pointrecordMapper.insert(pointrecord);
    }

    @Override
    public LoginVO loginData() {
        LoginVO loginVO = new LoginVO();

        //排行榜
        List<Memberinfo> rankList = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .orderByDesc(Memberinfo::getPoint)
                .last("limit 0,10").list();
        loginVO.setRankList(rankList);

        //在线人数
        Long onlineNum = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getIsonline, 1)
                .count();
        loginVO.setOnlineNum(onlineNum);


        return loginVO;
    }

    @Override
    public void findAccount(MemberInfoFindPassTO memberInfoFindPassTO) throws Exception {
        //判断参数是否合法
        if (MyUtil.StringIsBlank(memberInfoFindPassTO.getUserName())) {
            throw new MyException("用户名不能为空");
        }

        if (MyUtil.StringIsBlank(memberInfoFindPassTO.getPasswdAnswer())) {
            throw new MyException("密保问题不能为空");
        }

        if (MyUtil.StringIsBlank(memberInfoFindPassTO.getPasswdAnswer())) {
            throw new MyException("密保答案不能为空");
        }

        //数据库中查询用户信息
        Memberinfo memberinfo = new LambdaQueryChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname, memberInfoFindPassTO.getUserName())
                .one();

        if (!(memberinfo.getNickname().equals(memberInfoFindPassTO.getUserName().trim())
        &&memberinfo.getPasswordquestion().equals(memberInfoFindPassTO.getPasswdQuestion())
        &&memberinfo.getPasswordanswer().equals(memberInfoFindPassTO.getPasswdAnswer()))){
            throw new MyException("用户名或密保问题或密保答案错误!");
        }

        //生成新的用户密码
        String newPassword = RandomUtil.getRandomStr(8);

        //更新数据库中的密码  // TODO 密码加密
        new LambdaUpdateChainWrapper<>(memberinfoMapper)
                .eq(Memberinfo::getNickname,memberinfo.getNickname())
                .set(Memberinfo::getPassword,newPassword).update();

        //将新密码发送到指定的邮箱
        //得到用户邮箱
        String email = memberinfo.getEmail();
        //发送新密码给用户
        MailUtil.sendEmails(email,newPassword);
    }
}




